package com.service.user.impl;

import com.dao.*;
import com.entity.GoodsBasic;
import com.entity.Notice;
import com.entity.Order;
import com.entity.User;
import com.service.user.NoticeService;
import com.service.user.OrderService;
import com.service.user.UserService;
import com.service.user.WalletService;
import com.utils.SqlSessionGetter;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;
import io.netty.util.Timer;
import io.netty.util.TimerTask;

/**
 * 提供订单相关的服务
 */
@Service
public class OrderServiceImpl implements OrderService {

    private static Timer timer =
            new HashedWheelTimer(Executors.defaultThreadFactory(), 1, TimeUnit.SECONDS, 64);

    @Autowired
    NoticeService noticeService;
    @Autowired
    WalletService walletService;
    @Autowired
    UserService userService;

    @Override
    public String addAOrder(
            String userId, String goodId, int goodNum, String tradeWay, String grId, String remark) {
        // 生成随机的编号
        String orderId = UUID.randomUUID().toString().replace("-", "");
        SqlSession session = SqlSessionGetter.getSqlSession();
        OrderDao dao = session.getMapper(OrderDao.class);
        dao.insertAOrder(orderId, userId, goodId, goodNum, tradeWay, grId, remark);
        session.commit();
        session.close();
        // 添加订单倒计时
        timer.newTimeout(new ReadyPayOrder(orderId), 30, TimeUnit.MINUTES);
        return orderId;
    }

    @Override
    public List<Order> getOrdersByIds(List<String> orderIds) {
        SqlSession session = SqlSessionGetter.getSqlSession();
        OrderDao dao = session.getMapper(OrderDao.class);
        List<Order> orders = dao.selectOrdersByIds(orderIds);
        session.close();
        return orders;
    }

    @Override
    public int getBuyerOrderCount(String userId, int orderStatus) {
        SqlSession session = SqlSessionGetter.getSqlSession();
        OrderDao dao = session.getMapper(OrderDao.class);
        int count = dao.selectBuyerOrSellerOrderCount(userId, orderStatus, false);
        session.close();
        return count;
    }

    @Override
    public List<Order> getBuyerOrders(String userId, int orderStatus, int pageSize, int pageIndex) {
        SqlSession session = SqlSessionGetter.getSqlSession();
        OrderDao dao = session.getMapper(OrderDao.class);
        List<Order> orders =
                dao.selectBuyerOrSellerOrders(userId, orderStatus, pageIndex * pageSize, pageSize, false);
        session.close();
        return orders;
    }

    /**
     * 获取生成订单所需的信息
     *
     * @param goodId 商品编号
     * @return 生成订单所需的信息，包括商品基本信息和卖家
     */
    @Override
    public Map<String, Object> getCreateOrderInfo(String goodId) {
        List<Map<String, Object>> info = getCreateOrdersInfo(new String[]{goodId});
        return info.size() > 0 ? info.get(0) : null;
    }

    /**
     * 获取生成订单所需的信息
     *
     * @param goodIds 商品编号数组
     * @return 生成订单所需的信息，包括商品基本信息和卖家
     */
    @Override
    public List<Map<String, Object>> getCreateOrdersInfo(String[] goodIds) {
        List<Map<String, Object>> goodAndSellers = new ArrayList<>(goodIds.length);
        GoodsBasic gb;
        Map<String, Object> goodAndSeller;
        SqlSession session = SqlSessionGetter.getSqlSession();
        GoodsDao goodsDao = session.getMapper(GoodsDao.class);
        for (String goodId : goodIds) {
            // 获取商品基本信息
            gb = goodsDao.selectGoodBasicById(goodId, 1);
            if (gb != null && !"".equals(gb.getId())) {
                goodAndSeller = new HashMap<>(3);
                goodAndSeller.put("goodId", goodId);
                goodAndSeller.put("good", gb);

                // 获取买家信息
                Map<String, String> seller = goodsDao.selectSeller(goodId);
                goodAndSeller.put("seller", seller);
                goodAndSellers.add(goodAndSeller);
            }
        }
        session.close();
        return goodAndSellers;
    }

    @Override
    public int getWaitPayMaxPastMinutes(String[] orderIds) {
        SqlSession session = SqlSessionGetter.getSqlSession();
        OrderDao dao = session.getMapper(OrderDao.class);
        int max = dao.selectWaitPayMaxPastMinutes(Arrays.asList(orderIds));
        session.commit();
        session.close();
        return max;
    }

    /**
     * 取消订单 当且仅当订单状态为waitPay时才能被取消
     *
     * @param userId  用户编号
     * @param orderId 订单编号
     * @return 取消成功返回1，失败返回0
     */
    @Override
    public int deleteOrder(String userId, String orderId) {
        SqlSession session = SqlSessionGetter.getSqlSession();
        OrderDao dao = session.getMapper(OrderDao.class);
        int row = dao.deleteOrder(orderId);
        session.commit();
        session.close();
        return row;
    }

    @Override
    public int payWithCoin(String userId, String[] orderIds, float totalNum) {
        int payRet = walletService.pay(userId, totalNum);
        if (payRet == 0) {
            return 0;
        }
        return orderPaySuccess(orderIds);
    }

    @Override
    public int orderPaySuccess(String[] orderIds) {
        SqlSession session = SqlSessionGetter.getSqlSession();
        OrderDao dao = session.getMapper(OrderDao.class);
        int row = dao.updatePayInfo(Arrays.asList(orderIds));
        for (String orderId : orderIds) {
            dao.updateGoodsCountOrStatus(orderId);
        }
        session.commit();
        List<Order> orders = dao.selectOrdersByIds(Arrays.asList(orderIds));
        session.close();

        session = SqlSessionGetter.getSqlSession();
        NoticeDao noticeDao = session.getMapper(NoticeDao.class);
        GoodsBasic good;
        // 添加买家，卖家的支付通知,卖家货物变更通知
        for (Order order : orders) {
            noticeService.insertHelper(
                    noticeDao,
                    order.getBuyer().getId(),
                    Notice.ORDER_PAY_SUCCESS,
                    null,
                    1,
                    order.getOrderId());
            noticeService.insertHelper(
                    noticeDao,
                    order.getSeller().getId(),
                    Notice.BUYER_PAY_SUCCESS,
                    null,
                    0,
                    order.getOrderId());
            good = order.getGood();
            if (good.getStore() == 0) {
                // 商品数量变为0
                noticeService.insertHelper(
                        noticeDao,
                        order.getSeller().getId(),
                        Notice.PUT_OFF_GOOD_BECAUSE_OF_STORE,
                        null,
                        0,
                        good.getId(),
                        good.getName());
            }
        }
        session.commit();
        session.close();
        return row;
    }

    @Override
    public int confirmGood(String orderId) {
        SqlSession session = SqlSessionGetter.getSqlSession();
        OrderDao dao = session.getMapper(OrderDao.class);
        Map<String, Object> buyerSellerId = dao.selectBuyerSellerId(Arrays.asList(orderId)).get(0);
        String sellerId = (String) buyerSellerId.get("sellerId");
        float money = Float.parseFloat(buyerSellerId.get("money").toString());

        int incomeRet = walletService.income(sellerId, money);

        int ret = 0;
        if (incomeRet != 0) {
            try {
                ret = dao.updateConfirmGoodsInfo(orderId);
                session.commit();
            } catch (Exception e) {
                System.out.println("确认收货更新订单状态失败");
                e.printStackTrace();
            }
        }
        session.close();

        // 添加卖家通知
        noticeService.addNotice(sellerId, Notice.BUYER_CONFIRM_GOODS, null, 0, orderId, money);
        return ret;
    }

    @Override
    public int urgedDelivery(String orderId) {
        Order order = getOrdersByIds(Arrays.asList(orderId)).get(0);
        return noticeService.addNotice(
                order.getSeller().getId(), Notice.URGED_DELIVERY, null, 0, orderId);
    }

    @Override
    public List<Map<String, Object>> getAllFeedBack(int pageSize, int pageIndex) {
        SqlSession session = SqlSessionGetter.getSqlSession();
        OthersDao dao = session.getMapper(OthersDao.class);
        int start = pageIndex * pageSize;
        List<Map<String, Object>> managerPutOffComment =
                dao.selectAllFeedback(start, pageSize);
        session.close();

        for (Map<String, Object> item : managerPutOffComment) {
            String userId = (String) item.get("userId");
            User personalInfo = userService.getPersonalInfo(userId);
            item.put("userName", personalInfo.getName());
        }
        return managerPutOffComment;
    }

    @Override
    public int getAllFeedBackCount() {
        SqlSession session = SqlSessionGetter.getSqlSession();
        OthersDao dao = session.getMapper(OthersDao.class);
        int count = dao.getAllFeedBackCount();
        session.close();
        return count;
    }

    private class ReadyPayOrder implements TimerTask {
        String orderId;

        ReadyPayOrder(String id) {
            this.orderId = id;
        }

        @Override
        public void run(Timeout timeout) throws Exception {
            System.out.println("订单" + orderId + "超时取消");

            Order order = getOrdersByIds(Arrays.asList(orderId)).get(0);
            // 添加通知
            noticeService.addNotice(
                    order.getBuyer().getId(),
                    Notice.ORDER_TIMEOUT,
                    null,
                    0,
                    order.getCreateTime(),
                    order.getGood().getId(),
                    order.getGood().getName(),
                    order.getCount());
            // 删除超时订单
            deleteOrder(null, orderId);
        }
    }
}
